package com.qianya.oa.websocket;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qianya.oa.dto.websocket.WebsocketMessageDto;
import com.qianya.oa.service.SysUserMessageService;
import com.qianya.oa.vo.websocket.WebsocketMessageVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Component
public class MyWebSocketHandler extends TextWebSocketHandler {
    /**
     * 静态变量，用来记录当前在线连接数
     */
    private static AtomicInteger onlineNum = new AtomicInteger();

    /**
     * 客户端连接。一个账号在不同浏览器登录会有多个session
     */
    private static ConcurrentHashMap<Long, List<WebSocketSession>> sessionPools = new ConcurrentHashMap<>();

    /**
     * 在线人数加一
     */
    private static void addOnlineCount() {
        onlineNum.incrementAndGet();
    }

    /**
     * 在线人数减一
     */
    private static void subOnlineCount() {
        onlineNum.decrementAndGet();
    }

    @Resource
    private SysUserMessageService userMessageService;

    /**
     * 接受客户端消息
     *
     * @param session session
     * @param message message
     * @throws IOException e
     */
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        Long uid = Long.parseLong(session.getAttributes().get("uid").toString());

        ObjectMapper objectMapper = new ObjectMapper();
        WebsocketMessageDto wsMsg = objectMapper.readValue(message.getPayload(), WebsocketMessageDto.class);
        WebsocketMessageVo backWsMsg = new WebsocketMessageVo();

        switch (wsMsg.getMessageCode()) {
            case "1":
                //拉取并阅读最近消息
                Object result;
                //成功
                result = userMessageService.getAndReadMessage(uid, wsMsg.getPageNum(), wsMsg.getPageSize());
                backWsMsg.setResultCode("201");
                backWsMsg.setMessageData(JSON.toJSONString(result));
                log.info(String.format("收到用户：【%s】的拉取请求", session.getAttributes().get("uid")));
                break;
            case "2":
                //获取未读消息数量
                int unreadCount = userMessageService.getUnreadCount(uid);
                backWsMsg.setResultCode("202");
                backWsMsg.setMessageData(String.valueOf(unreadCount));
            default:
        }

        session.sendMessage(new TextMessage(JSON.toJSONString(backWsMsg)));
    }

    /**
     * 建立连接后发送消息给客户端
     *
     * @param session session
     * @throws Exception e
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String uid = session.getAttributes().get("uid").toString();
        String fromUserName = session.getAttributes().get("realName").toString();
        addSessionToPool(session, uid, sessionPools);
        addOnlineCount();

        //建立连接之后返回聊天信息未读数 + 消息通知
        log.info("uid：【" + uid + "】，session：【" + session.getId() + "】，用户：【" + fromUserName + "】已连接");
        log.info("当前连接数：" + onlineNum);
        log.info("实际在线管理员：" + sessionPools.size() + "实际在线用户：" + sessionPools.size());
        WebsocketMessageVo backWsMsg = new WebsocketMessageVo();
        backWsMsg.setResultCode("100");
        backWsMsg.setMessageData("欢迎你：" + fromUserName);
        session.sendMessage(new TextMessage(JSON.toJSONString(backWsMsg)));
    }

    /**
     * 添加session到session池
     *
     * @param session
     * @param uid
     * @param sessionPools
     */
    private void addSessionToPool(WebSocketSession session, String uid, ConcurrentHashMap<Long, List<WebSocketSession>> sessionPools) {
        List<WebSocketSession> webSocketSessionList = sessionPools.get(Long.parseLong(uid));
        if (webSocketSessionList == null) {
            ArrayList<WebSocketSession> arrayList = new ArrayList<>();
            arrayList.add(session);
            sessionPools.put(Long.parseLong(uid), arrayList);
        } else {
            webSocketSessionList.add(session);
        }
    }

    /**
     * 从session池移除session
     *
     * @param session
     * @param uid
     * @param sessionPools
     */
    private void removeSessionToPool(WebSocketSession session, String uid, ConcurrentHashMap<Long, List<WebSocketSession>> sessionPools) {
        List<WebSocketSession> webSocketSessionList = sessionPools.get(Long.parseLong(uid));
        if (webSocketSessionList != null) {
            webSocketSessionList.remove(session);
        }
    }

    /**
     * 连接关闭后
     *
     * @param session session
     * @param status  status
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        String uid = session.getAttributes().get("uid").toString();
        String realName = session.getAttributes().get("realName").toString();
        removeSessionToPool(session, uid, sessionPools);
        subOnlineCount();
        log.info("uid：【" + uid + "】，session：【" + session.getId() + "】，用户：【" + realName + "】断开连接");
        log.info("当前连接数：" + onlineNum);
    }

    /**
     * 发送广播消息
     *
     * @param message 消息内容
     */
    public static void sendTopic(String message) {
        if (sessionPools.isEmpty()) {
            return;
        }
        TextMessage webSocketMessage = new TextMessage(message);
        for (Map.Entry<Long, List<WebSocketSession>> entry : sessionPools.entrySet()) {
            try {
                List<WebSocketSession> value = entry.getValue();
                for (WebSocketSession webSocketSession : value) {
                    webSocketSession.sendMessage(webSocketMessage);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 发送消息
     *
     * @param websocketMessage
     */
    public static void sendTo(WebsocketMessageDto websocketMessage) {
        //要发送目标的session集合
        List<WebSocketSession> socketSessionList;
        socketSessionList = sessionPools.get(websocketMessage.getToUserId());
        //是否在线
        if (socketSessionList != null && socketSessionList.size() > 0) {
            //发送成功
            websocketMessage.setResultCode("200");
            TextMessage webSocketMessage = new TextMessage(JSON.toJSONString(websocketMessage));
            try {
                for (WebSocketSession socketSession : socketSessionList) {
                    socketSession.sendMessage(webSocketMessage);
                }
            } catch (Exception e) {
                log.error("发送者错误! 信息:{}", websocketMessage);
            }
        }
    }

}
